package cn.com.chengq.oa;

import cn.com.chengq.oa.spi.SalaryCalerService;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.ServiceLoader;

public class OADemo {
    public static void main(String[] args) throws Exception {
        Double salary = 2000.00;
        Double money;

        // 将计算工资的部分分离一个以Jar包，然后通过网络加载
        // 下面模拟每隔一段时间，重新计算薪水
        // ClassLoader classLoader = getClassLoaderByCustomizeJar1();
        ClassLoader classLoader = null;
        classLoader = getClassLoaderByCustomizeJar1();
        while (true) {
            // 由于缓存的存在，不能实现热加载
            // 但是我们可以通过每次重新生成一个类加载器来实现热加载。
            money = calSalary(salary, classLoader);
            System.out.println("实际到手的工资: " + money);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }

    private static Double calSalary(Double salary, ClassLoader classLoader) throws Exception {
//        Class<?> clazz = null;
//        int reTry = 30;
//        String className = "cn.com.chengq.oa.SalaryCaler";
//        while (clazz == null && reTry != 0) {
//            try {
//                clazz = classLoader.loadClass(className);
//            } catch (Exception ex) {
//                Thread.sleep(1000);
//                System.out.println(String.format("第 %d 次重试加载: %s", 30 - reTry + 1, className));
//                reTry--;
//            }
//        }

        // 1. 实现方式1
        // SalaryCaler caler = new SalaryCaler();
        // return caler.cal(salary);

        // 2. 实现方式2
//        Object obj = clazz.newInstance();
//        Method calMethod = clazz.getMethod("cal", Double.class);
//        return (Double) calMethod.invoke(obj, salary);

        // 3. 实现方式3

        ServiceLoader<SalaryCalerService> serviceLoader = ServiceLoader.load(SalaryCalerService.class, classLoader);
        Iterator<SalaryCalerService> services = serviceLoader.iterator();
        Double result = -1.0;
        while (services.hasNext()) {
            SalaryCalerService service = services.next();
            result =  service.cal(salary);
            System.out.println(result);
        }

        return result;
    }

    private static ClassLoader getClassLoaderFromLocal() throws Exception {
        URL url = new URL("file:G:\\workspace\\spring-framework-projects\\salarycaler\\target\\salarycaler-1.0.0.jar");
        ClassLoader classLoader = new URLClassLoader(new URL[]{url});
        return classLoader;
    }

    private static ClassLoader getClassLoaderFromNetwork() throws Exception {
        URL url = new URL("http://127.0.0.1:8080/examples/salarycaler-1.0.0.jar");
        ClassLoader classLoader = new URLClassLoader(new URL[]{url});
        return classLoader;
    }

    private static ClassLoader getClassLoaderByCustomize() {
        String classPath = "G:\\workspace\\spring-framework-projects\\salarycaler\\target\\classes\\";
        SalaryClassLoader classLoader = new SalaryClassLoader(classPath);
        return classLoader;
    }

    private static ClassLoader getClassLoaderByCustomizeJar() throws Exception {
        String jarPath = "file:\\G:\\workspace\\spring-framework-projects\\salarycaler\\target\\salarycaler-1.0.0.jar";
        SalaryJarClassLoader classLoader = new SalaryJarClassLoader(new URL[]{new URL(jarPath)});
        return classLoader;
    }

    private static ClassLoader getClassLoaderByCustomizeJar1() throws Exception {
        String jarPath = "http://127.0.0.1:8080/examples/salarycaler-1.0.0.jar";
        // System.out.println("创建新的类加载器");
        SalaryJarClassLoader classLoader = new SalaryJarClassLoader(new URL[]{new URL(jarPath)});

        return classLoader;
    }
}
